/*
This file is part of CanFestival, a library implementing CanOpen Stack.

Copyright (C): Edouard TISSERANT and Francis DUPIN

See COPYING file for copyrights details.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>

/* driver pcan pci for Peak board */
//#include "libpcan.h"
//#include "pcan.h"

#include "controlcan.h" // for CAN_HANDLE

#include "can_driver.h"

// Define for rtr CAN message
#define CAN_INIT_TYPE_ST_RTR 1 // MSGTYPE_STANDARD | MSGTYPE_RTR
#define CAN_INIT_TYPE_ST 0

#define MAX_CHANNELS 1
#define CHECK_POINT 200
#define RX_WAIT_TIME 100
#define RX_BUFF_SIZE 1000

unsigned gDevType = 4;
unsigned gDevIdx = 0;
unsigned gChMask = 0;
unsigned gBaud = 0;
unsigned gTxType = 0;
unsigned gTxSleep = 0;
unsigned gTxFrames = 1;
unsigned gTxCount = 0;

// FILE *file;
// file = fopen("file.txt", "w"); // 打开文件
/*********functions which permit to communicate with the board****************/
UNS8 canReceive_driver(CAN_HANDLE fd0, Message *m)
{
  // file = fopen("file.txt", "a"); // 打开文件/
  VCI_CAN_OBJ can;
  time_t tm1, tm2;
  VCI_Receive(gDevType, gDevIdx, 0, &can, 1, -1);
  m->cob_id = can.ID;
  if (can.RemoteFlag == 0) /* bits of MSGTYPE_*/
    m->rtr = 0;
  else
    m->rtr = 1;
  m->len = can.DataLen; /* count of data bytes (0..8) */
  // fprintf(file, "CAN%d RX : ID=%08x    data:=", 0, m->cob_id);
  for (int data = 0; data < can.DataLen; data++)
  {
    m->data[data] = can.Data[data];
    // fprintf(file, "%08x        ", m->data[data]);
  }
  // fprintf(file, "\n");
  // fclose(file);
  return 0;
}

/***************************************************************************/
UNS8 canSend_driver(CAN_HANDLE fd0, Message const *m)
{
  // ----- start transmit -----------------------------------------------
  VCI_CAN_OBJ *buff = (VCI_CAN_OBJ *)malloc(sizeof(VCI_CAN_OBJ) * gTxFrames);
  buff->ID = m->cob_id; /* 11/29 bit code */
  if (m->rtr == 0)
    buff->RemoteFlag = CAN_INIT_TYPE_ST; /* bits of MSGTYPE_*/
  else
  {
    buff->RemoteFlag = CAN_INIT_TYPE_ST_RTR; /* bits of MSGTYPE_*/
  }
  buff->DataLen = m->len;
  /* count of data bytes (0..8) */
  // fprintf(file, "CAN%d TX : ID=%08x    data:=", 0, buff->ID);
  for (int data = 0; data < m->len; data++)
  {
    buff->Data[data] = m->data[data];
    // fprintf(file, "%08x      ", buff->Data[data]);
  }
  // fprintf(file, "\n");
  int err = 0;
  if (gTxFrames != VCI_Transmit(gDevType, gDevIdx, 0, &buff[0], 1))
  {
    printf("CAN%d TX failed: ID=%08x\n", 0, buff->ID);
    err = 1;
  }
  // fclose(file);
  free(buff);
}

/***************************************************************************/
int TranslateBaudeRate(char *optarg)
{
  // if (!strcmp(optarg, "1M"))
  //   return CAN_BAUD_1M;
  // if (!strcmp(optarg, "500K"))
  //   return CAN_BAUD_500K;
  // if (!strcmp(optarg, "250K"))
  //   return CAN_BAUD_250K;
  // if (!strcmp(optarg, "125K"))
  //   return CAN_BAUD_125K;
  // if (!strcmp(optarg, "100K"))
  //   return CAN_BAUD_100K;
  // if (!strcmp(optarg, "50K"))
  //   return CAN_BAUD_50K;
  // if (!strcmp(optarg, "20K"))
  //   return CAN_BAUD_20K;
  // if (!strcmp(optarg, "10K"))
  //   return CAN_BAUD_10K;
  // if (!strcmp(optarg, "5K"))
  //   return CAN_BAUD_5K;
  // if (!strcmp(optarg, "none"))
  //   return 0;
  return 0x0000;
}

UNS8 canChangeBaudRate_driver(CAN_HANDLE fd, char *baud)
{
  printf("canChangeBaudRate not yet supported by this driver\n");
  return 0;
}

/***************************************************************************/
CAN_HANDLE canOpen_driver(s_BOARD *board)
{
  if (!VCI_OpenDevice(gDevType, gDevIdx, 0))
  {
    printf("VCI_OpenDevice failed\n");
    printf("VCI_OpenDevice failed\n");
    return 0;
  }
  printf("VCI_OpenDevice succeeded\n");

  // ----- init & start -------------------------------------------------

  VCI_INIT_CONFIG config;
  config.AccCode = 0;
  config.AccMask = 0xffffffff;
  config.Filter = 1;
  config.Mode = 0;
  config.Timing0 = gBaud & 0xff;
  config.Timing1 = 0x14; // >> 8;

  int i, j;
  for (i = 0; i < MAX_CHANNELS; i++)
  {
    // if ((gChMask & (1 << i)) == 0)
    //   continue;

    if (!VCI_InitCAN(gDevType, gDevIdx, i, &config))
    {
      printf("VCI_InitCAN(%d) failed\n", i);
      return 0;
    }
    printf("VCI_InitCAN(%d) succeeded\n", i);

    if (!VCI_StartCAN(gDevType, gDevIdx, i))
    {
      printf("VCI_StartCAN(%d) failed\n", i);
      return 0;
    }
    printf("VCI_StartCAN(%d) succeeded\n", i);
  }
  return 0;
}

/***************************************************************************/
int canClose_driver(CAN_HANDLE fd0)
{
  // CAN_Close(fd0);
  VCI_CloseDevice(gDevType, gDevIdx);
  printf("VCI_CloseDevice\n");
  return 0;
}
